package edu.chalmers.gos;

import java.util.ArrayList;
import java.util.HashMap;

import org.cocos2d.nodes.CCLabel;
import org.cocos2d.nodes.CCNode;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.nodes.CCSpriteFrame;
import org.cocos2d.nodes.CCSpriteSheet;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.CGRect;

import edu.chalmers.gos.Cards.Card;
import edu.chalmers.targine.ARManager;
import edu.chalmers.targine.CocosComponent;

/**Interface for performing actions with the player's character*/
public class HandInterface implements CocosComponent{
	//Fields
	private CCNode _spriteNode;
	private CCSpriteSheet _actionIcons;
	private ArrayList<CCSprite> _slots = new ArrayList<CCSprite>();
	private ArrayList<CCSprite> _icons = new ArrayList<CCSprite>();
	private HashMap<String, CCSpriteFrame> _contentFrames = new HashMap<String, CCSpriteFrame>();
	private ArrayList<String> _contentStrings = new ArrayList<String>();
	private ArrayList<Card> _cards = new ArrayList<Card>();
	private int _currentSlot, _selectedSlot, _touchID;
	private CGPoint _touchPoint, _startTouchPoint;
	private boolean _isTouched;
	private boolean _isSelected;
	private float _goalAngle, _currentAngle;
	private int _animationState = 0;
	
	private static String CARD_BD_IMG = "card_bd.png";
	
	/**Constructor initializes graphics, position and touch*/
	public HandInterface(String imageFile,  float startX, float startY){
		_spriteNode = CCNode.node();
		_spriteNode.setPosition(CGPoint.ccp(startX, startY));
		_isTouched = _isSelected = false;
		_currentSlot = _selectedSlot = 0;
		_touchID = -1;
		_goalAngle = (float)Math.toRadians(270);
		_currentAngle = (float)Math.toRadians(270);
		
		for(int i = 0; i < 3; i++){
			_icons.add(CCSprite.sprite("colors.png", CGRect.make(i * 25, 0, 25, 25)));
		}
//		_spriteNode.setVisible(false);
	}
	
	public void loadCards(String imageFile, HashMap<String, Card> cards){
		_actionIcons = CCSpriteSheet.spriteSheet(imageFile);
		for(Card card : cards.values()){
			_contentFrames.put(
				card.name,
				CCSpriteFrame.frame(
					_actionIcons.getTexture(),
					CGRect.make(card.id * 100, 0, 100, 100),
					CGPoint.ccp(88,  88)
				)
			);
		}
	}
	
	/**Action slots' behavior*/
	public void update(float dt, ARManager arManager){
		if(_slots.isEmpty()){
			return; 
		}
		//Put current slot in front
		_spriteNode.reorderChild(_slots.get(_currentSlot), 0);
		//Correct angles according to touch
		if(_isTouched){
			float dist = _startTouchPoint.x - _touchPoint.x;
			_currentAngle = _goalAngle - dist / 150 * (float)Math.PI * 0.3f;
		}
		//Correct angles according to which one is the current slot
		else{
			if(_currentAngle < _goalAngle){
				_currentAngle += Math.toRadians(360 * dt);
				_currentAngle = Math.min(_currentAngle, _goalAngle);
			} else if(_currentAngle > _goalAngle){
				_currentAngle -= Math.toRadians(360 * dt);
				_currentAngle = Math.max(_currentAngle, _goalAngle);
			}
		}
		float slotDist = (float)Math.PI * 2 / _slots.size();
		//Set scale of a slot in relation to its angle
		for(int i = 0; i < _slots.size(); i++){
			int yOffset = 0;
			if(_isSelected && i == _selectedSlot){
				yOffset = 75;
			}
			CCSprite sprite = _slots.get(i);
			sprite.setPosition(
				(float)Math.cos(_currentAngle + i * (slotDist)) * 88,
				(float)Math.sin(_currentAngle + i * (slotDist)) * 32 + yOffset);
			sprite.setScale(
				(float)Math.cos(_currentAngle + i * (slotDist) + Math.PI * 0.5) * 0.3f + 0.7f);
		}
	}
	
	public void add(Card card){ 
		CCSprite actionSlot = CCSprite.sprite(CARD_BD_IMG);
//		CCSprite image = new CCSprite();
		CCLabel title = CCLabel.makeLabel(card.name, "Verdana", 10);
		title.setPosition(CGPoint.ccp(
				actionSlot.getTexture().getWidth() / 2,
				actionSlot.getTexture().getHeight() - 20f));
		String contentString = "";
		if(card.hasType(Card.PLOT)){
			contentString = "I:" + card.initiative + " P:" + card.production;
		} else if(card.hasType(Card.UNIT)){
			contentString =
					"T:" + card.type +
					" C:" + card.cost +
					" Pwr:" +  card.power;
			if(card.red){
				CCSprite red = CCSprite.sprite(_icons.get(0).displayedFrame());
				red.setPosition(CGPoint.ccp(15, 85));
				actionSlot.addChild(red);
			} if(card.green){
				CCSprite green = CCSprite.sprite(_icons.get(1).displayedFrame());
				green.setPosition(CGPoint.ccp(15, 60));
				actionSlot.addChild(green);
			} if(card.blue){
				CCSprite blue = CCSprite.sprite(_icons.get(2).displayedFrame());
				blue.setPosition(CGPoint.ccp(15, 35));
				actionSlot.addChild(blue);
			}
		} else if(card.hasType(Card.LAND)){
			contentString = "Production: " + card.production;
		}
		CCLabel content = CCLabel.makeLabel(contentString, "Verdana", 10);
		content.setPosition(CGPoint.ccp(
				actionSlot.getTexture().getWidth() / 2,
				actionSlot.getTexture().getHeight() - 40f));
//		actionSlot.addChild(image);
		actionSlot.addChild(title);
		actionSlot.addChild(content);
		
		_contentStrings.add(card.name);
		_cards.add(card);
		_spriteNode.addChild(actionSlot);
		_slots.add(actionSlot);
	}
	
	public void clear(){
		_contentStrings.clear();
		_cards.clear();
		_spriteNode.removeAllChildren(true);
		_slots.clear();
		_selectedSlot = 0;
		_isSelected = false;
		_currentSlot = 0;
		_currentAngle = 0;
		_goalAngle = (float)Math.toRadians(270);
	}
	
	////GETTERS, SETTERS AND HELP METHODS
	/** */
	public void swapActions(){
		float dist = _startTouchPoint.x - _touchPoint.x;
		//
		if(dist < 0){
			_goalAngle += Math.toRadians(360 / _slots.size());
			_currentSlot = (_currentSlot + _slots.size() - 1) % _slots.size();
		}
		//
		else{
			_goalAngle -= Math.toRadians(360 / _slots.size());
			_currentSlot = (_currentSlot + 1) % _slots.size();
		}
		System.out.println("swap action");
	}
	
	/** */
	public boolean isIntersecting(CGRect otherRect){
		CGRect boundingBox = CGRect.make(
				_spriteNode.getPosition().x - 96,
				_spriteNode.getPosition().y - 66,
				200,
				150);
		return CGRect.intersects(boundingBox, otherRect);
	}
	
	/** */
	public boolean hasTouchID(int touchID){
		return _touchID == touchID;
	}
	
	/** */
	public boolean wasSwiped(){
		if(_startTouchPoint == null){
			return false;
		}
		float dist = (float)Math.hypot(
				_startTouchPoint.x - _touchPoint.x,
				_startTouchPoint.y - _touchPoint.y);
		System.out.println("was swiped");
		return dist > 55;
	}
	
	/** */
	public void setVisible(boolean visible){
		_spriteNode.setVisible(visible);
		if(!visible){
			_isTouched = false;
			_touchID = -1;
			_touchPoint = null;
			_startTouchPoint = null;
		}
	}
	
	public boolean isVisible(){
		return _spriteNode.getVisible();
	}
	
	/** */
	public void setContent(int contentIndex, String content){
		_slots.get(contentIndex).setDisplayFrame(_contentFrames.get(content));
	}
	
	public void addContent(String contentName){
		_contentStrings.add(contentName);
		//Create sprites for slot and icon
		CCSprite actionSlot = CCSprite.sprite("activeSlot.png");
		CCSprite slotContent = new CCSprite();
		slotContent.setDisplayFrame(_contentFrames.get(contentName));
		//Add content to slot and then slot to parent and array
		actionSlot.addChild(slotContent);
		_spriteNode.addChild(actionSlot);
		_slots.add(actionSlot);
	}
	
	/** */
	public String getContent(int contentIndex){
		return _contentStrings.get(contentIndex);
	}
	
	public boolean contentIs(String content){
		return _contentStrings.get(_currentSlot).equals(content);
	}
	
	/** */
	public String getCurrentAction(){
		return _contentStrings.get(_currentSlot);
	}
	
	public Card getCurrentCard(){
		return _cards.get(_currentSlot);
	}

	public void touchBegan(int touchID, CGPoint touchPoint) {
		_isTouched = true;
		_touchID = touchID;
		_touchPoint = touchPoint;
		_startTouchPoint = touchPoint;
	}
	
	/** */
	public void updateTouch(int touchID, CGPoint touchPoint){
		if(hasTouchID(touchID)){
			_touchPoint = touchPoint;
		} else{
			touchBegan(touchID, touchPoint);
		}
	}

	public void touchEnded(int touchID, ARManager arManager){
		if(wasSwiped()){
			swapActions();
		} else{
			_isSelected = !_isSelected;
			_selectedSlot = _currentSlot;
			arManager.performTapAction("CARD", getCurrentCard());
		}
		_isTouched = false;
		_touchID = -1;
		_touchPoint = null;
		_startTouchPoint = null;
	}
	
	public void setSelected(boolean selected){
		_isSelected = selected;
	}
	
	/** */
	public CCNode getNode(){
		return _spriteNode;
	}
}
